﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../ALMANAC.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace BDSEPHEMERISDecoder
{
using Sync   = TAO_PEGTL_STRING("#BDSEPHEMERISA");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
// clang-format off
struct SatelliteID : star<digit> {};
struct Week : star<digit> {};
struct URA : Floating {};
struct Health1 : star<digit> {};
struct Tgd1 : Floating {};
struct Tgd2 : Floating {};
struct AODC : star<digit> {};
struct TOC : star<digit> {};
struct A0 : Floating {};
struct A1 : Floating {};
struct A2 : Floating {};
struct AODE : star<digit> {};
struct TOE : star<digit> {};
struct ROOTA : Floating {};
struct ECC : Floating {};
struct Omega : Floating {};
struct DeltaN : Floating {};
struct M0 : Floating {};
struct Ohm0 : Floating {};
struct Ohm : Floating {};
struct I0 : Floating {};
struct IDOT : Floating {};
struct Cuc : Floating {};
struct Cus : Floating {};
struct Crc : Floating {};
struct Crs : Floating {};
struct Cic : Floating {};
struct Cis : Floating {};
// clang-format on

using Expression = seq<Header,
                       SatelliteID,
                       Split,
                       Week,
                       Split,
                       URA,
                       Split,
                       Health1,
                       Split,
                       Tgd1,
                       Split,
                       Tgd2,
                       Split,
                       AODC,
                       Split,
                       TOC,
                       Split,
                       A0,
                       Split,
                       A1,
                       Split,
                       A2,
                       Split,
                       AODE,
                       Split,
                       TOE,
                       Split,
                       ROOTA,
                       Split,
                       ECC,
                       Split,
                       Omega,
                       Split,
                       DeltaN,
                       Split,
                       M0,
                       Split,
                       Ohm0,
                       Split,
                       Ohm,
                       Split,
                       I0,
                       Split,
                       IDOT,
                       Split,
                       Cuc,
                       Split,
                       Cus,
                       Split,
                       Crc,
                       Split,
                       Crs,
                       Split,
                       Cic,
                       Split,
                       Cis,
                       one<'*'>,
                       CRC32,
                       Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<SatelliteID> : IntHelper<Action<SatelliteID>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.satelliteID = value; }
};

template<>
struct Action<Week> : IntHelper<Action<Week>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.week = value; }
};

template<>
struct Action<URA> : DoubleHelper<Action<URA>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.ura = value; }
};

template<>
struct Action<Health1> : IntHelper<Action<Health1>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.health1 = value; }
};

template<>
struct Action<Tgd1> : DoubleHelper<Action<Tgd1>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.tgd1 = value; }
};

template<>
struct Action<Tgd2> : DoubleHelper<Action<Tgd2>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.tgd2 = value; }
};

template<>
struct Action<AODC> : IntHelper<Action<AODC>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.aodc = value; }
};

template<>
struct Action<TOC> : IntHelper<Action<TOC>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.toc = value; }
};

template<>
struct Action<A0> : DoubleHelper<Action<A0>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.a0 = value; }
};

template<>
struct Action<A1> : DoubleHelper<Action<A1>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.a1 = value; }
};

template<>
struct Action<A2> : DoubleHelper<Action<A2>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.a2 = value; }
};

template<>
struct Action<AODE> : IntHelper<Action<AODE>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.aode = value; }
};

template<>
struct Action<TOE> : IntHelper<Action<TOE>, uint32_t>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.toe = value; }
};

template<>
struct Action<ROOTA> : DoubleHelper<Action<ROOTA>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.rootA = value; }
};

template<>
struct Action<ECC> : DoubleHelper<Action<ECC>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.ecc = value; }
};

template<>
struct Action<Omega> : DoubleHelper<Action<Omega>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.omega = value; }
};

template<>
struct Action<DeltaN> : DoubleHelper<Action<DeltaN>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.deltaN = value; }
};

template<>
struct Action<M0> : DoubleHelper<Action<M0>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.m0 = value; }
};

template<>
struct Action<Ohm0> : DoubleHelper<Action<Ohm0>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.ohm0 = value; }
};

template<>
struct Action<Ohm> : DoubleHelper<Action<Ohm>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.ohm = value; }
};

template<>
struct Action<I0> : DoubleHelper<Action<I0>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.i0 = value; }
};

template<>
struct Action<IDOT> : DoubleHelper<Action<IDOT>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.idot = value; }
};

template<>
struct Action<Cuc> : DoubleHelper<Action<Cuc>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.cuc = value; }
};

template<>
struct Action<Cus> : DoubleHelper<Action<Cus>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.cus = value; }
};

template<>
struct Action<Crc> : DoubleHelper<Action<Crc>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.crc = value; }
};

template<>
struct Action<Crs> : DoubleHelper<Action<Crs>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.crs = value; }
};

template<>
struct Action<Cic> : DoubleHelper<Action<Cic>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.cic = value; }
};

template<>
struct Action<Cis> : DoubleHelper<Action<Cis>>
{
    static void setValue(BDSEPHEMERIS::Data& data, double value) { data.cis = value; }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(BDSEPHEMERIS::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace BDSEPHEMERISDecoder
} // namespace GnssLogs